home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / gg / ncurses-5.3.lha / ncurses-5.3 / c++ / cursesm.cc < prev    next >
C/C++ Source or Header  |  2002-10-24  |  10KB  |  384 lines

  1. // * this is for making emacs happy: -*-Mode: C++;-*-
  2. /****************************************************************************
  3.  * Copyright (c) 1998,1999,2001 Free Software Foundation, Inc.              *
  4.  *                                                                          *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a  *
  6.  * copy of this software and associated documentation files (the            *
  7.  * "Software"), to deal in the Software without restriction, including      *
  8.  * without limitation the rights to use, copy, modify, merge, publish,      *
  9.  * distribute, distribute with modifications, sublicense, and/or sell       *
  10.  * copies of the Software, and to permit persons to whom the Software is    *
  11.  * furnished to do so, subject to the following conditions:                 *
  12.  *                                                                          *
  13.  * The above copyright notice and this permission notice shall be included  *
  14.  * in all copies or substantial portions of the Software.                   *
  15.  *                                                                          *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
  17.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
  18.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
  19.  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
  20.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
  21.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
  22.  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
  23.  *                                                                          *
  24.  * Except as contained in this notice, the name(s) of the above copyright   *
  25.  * holders shall not be used in advertising or otherwise to promote the     *
  26.  * sale, use or other dealings in this Software without prior written       *
  27.  * authorization.                                                           *
  28.  ****************************************************************************/
  29.  
  30. /****************************************************************************
  31.  *   Author: Juergen Pfeifer, 1997                                          *
  32.  *   Contact: http://www.familiepfeifer.de/Contact.aspx?Lang=en             *
  33.  ****************************************************************************/
  34.  
  35. #include "internal.h"
  36. #include "cursesm.h"
  37. #include "cursesapp.h"
  38.  
  39. MODULE_ID("$Id: cursesm.cc,v 1.17 2002/07/06 15:47:52 juergen Exp $")
  40.  
  41. NCursesMenuItem::~NCursesMenuItem() {
  42.   if (item)
  43.     OnError(::free_item(item));
  44. }
  45.  
  46. bool
  47. NCursesMenuItem::action() {
  48.   return FALSE;
  49. };
  50.  
  51. NCursesMenuCallbackItem::~NCursesMenuCallbackItem() {
  52. }
  53.  
  54. bool
  55. NCursesMenuCallbackItem::action() {
  56.   if (p_fct)
  57.     return p_fct (*this);
  58.   else
  59.     return FALSE;
  60. }
  61.  
  62. /* Internal hook functions. They will route the hook
  63.  * calls to virtual methods of the NCursesMenu class,
  64.  * so in C++ providing a hook is done simply by
  65.  * implementing a virtual method in a derived class
  66.  */
  67. void
  68. NCursesMenu::mnu_init(MENU *m) {
  69.   getHook(m)->On_Menu_Init();
  70. }
  71.  
  72. void
  73. NCursesMenu::mnu_term(MENU *m) {
  74.   getHook(m)->On_Menu_Termination();
  75. }
  76.  
  77. void
  78. NCursesMenu::itm_init(MENU *m) {
  79.   NCursesMenu* M = getHook(m);
  80.   M->On_Item_Init (*(M->current_item ()));
  81. }
  82.  
  83. void
  84. NCursesMenu::itm_term(MENU *m) {
  85.   NCursesMenu* M = getHook(m);
  86.   M->On_Item_Termination (*(M->current_item ()));
  87. }
  88.  
  89. /* Construct an ITEM* array from an array of NCursesMenuItem
  90.  * objects.
  91.  */
  92. ITEM**
  93. NCursesMenu::mapItems(NCursesMenuItem* nitems[]) {
  94.   int itemCount = 0,lcv;
  95.  
  96.   for (lcv=0; nitems[lcv]->item; ++lcv)
  97.     ++itemCount;
  98.  
  99.   ITEM** items = new ITEM*[itemCount + 1];
  100.  
  101.   for (lcv=0;nitems[lcv]->item;++lcv) {
  102.     items[lcv] = nitems[lcv]->item;
  103.   }
  104.   items[lcv] = NULL;
  105.  
  106.   my_items = nitems;
  107.  
  108.   if (menu)
  109.     delete[] ::menu_items(menu);
  110.   return items;
  111. }
  112.  
  113. void
  114. NCursesMenu::InitMenu(NCursesMenuItem* nitems[],
  115.               bool with_frame,
  116.               bool autoDelete_Items) {
  117.   int mrows, mcols;
  118.  
  119.   keypad(TRUE);
  120.   meta(TRUE);
  121.  
  122.   b_framed = with_frame;
  123.   b_autoDelete = autoDelete_Items;
  124.  
  125.   menu = (MENU*)0;
  126.   menu = ::new_menu(mapItems(nitems));
  127.   if (!menu)
  128.     OnError (E_SYSTEM_ERROR);
  129.  
  130.   UserHook* hook = new UserHook;
  131.   hook->m_user   = NULL;
  132.   hook->m_back   = this;
  133.   hook->m_owner  = menu;
  134.   ::set_menu_userptr(menu,(void*)hook);
  135.  
  136.   ::set_menu_init (menu, NCursesMenu::mnu_init);
  137.   ::set_menu_term (menu, NCursesMenu::mnu_term);
  138.   ::set_item_init (menu, NCursesMenu::itm_init);
  139.   ::set_item_term (menu, NCursesMenu::itm_term);
  140.  
  141.   scale(mrows, mcols);
  142.   ::set_menu_win(menu, w);
  143.  
  144.   if (with_frame) {
  145.     if ((mrows > height()-2) || (mcols > width()-2))
  146.       OnError(E_NO_ROOM);
  147.     sub = new NCursesWindow(*this,mrows,mcols,1,1,'r');
  148.     ::set_menu_sub(menu, sub->w);
  149.     b_sub_owner = TRUE;
  150.   }
  151.   else {
  152.     sub = (NCursesWindow*)0;
  153.     b_sub_owner = FALSE;
  154.   }
  155.   setDefaultAttributes();
  156. }
  157.  
  158. void
  159. NCursesMenu::setDefaultAttributes() {
  160.   NCursesApplication* S = NCursesApplication::getApplication();
  161.   if (S) {
  162.     ::set_menu_fore(menu, S->foregrounds());
  163.     ::set_menu_back(menu, S->backgrounds());
  164.     ::set_menu_grey(menu, S->inactives());
  165.   }
  166. }
  167.  
  168. NCursesMenu::~NCursesMenu() {
  169.   UserHook* hook = (UserHook*)::menu_userptr(menu);
  170.   delete hook;
  171.   if (b_sub_owner) {
  172.     delete sub;
  173.     ::set_menu_sub(menu,(WINDOW *)0);
  174.   }
  175.   if (menu) {
  176.     ITEM** itms = ::menu_items(menu);
  177.     int cnt = count();
  178.  
  179.     OnError(::set_menu_items(menu,(ITEM**)0));
  180.  
  181.     if (b_autoDelete) {
  182.       if (cnt>0) {
  183.     for (int i=0; i <= cnt; i++)
  184.       delete my_items[i];
  185.       }
  186.       delete[] my_items;
  187.     }
  188.  
  189.     ::free_menu(menu);
  190.     // It's essential to do this after free_menu()
  191.     delete[] itms;
  192.   }
  193. }
  194.  
  195. void
  196. NCursesMenu::setSubWindow(NCursesWindow& nsub) {
  197.   if (!isDescendant(nsub))
  198.     OnError(E_SYSTEM_ERROR);
  199.   else {
  200.     if (b_sub_owner)
  201.       delete sub;
  202.     sub = ⊄
  203.     ::set_menu_sub(menu,sub->w);
  204.   }
  205. }
  206.  
  207. bool
  208. NCursesMenu::set_pattern (const char *pat) {
  209.   int res = ::set_menu_pattern (menu, pat);
  210.   switch(res) {
  211.   case E_OK:
  212.     break;
  213.   case E_NO_MATCH:
  214.     return FALSE;
  215.   default:
  216.     OnError (res);
  217.   }
  218.   return TRUE;
  219. }
  220.  
  221. // call the menu driver and do basic error checking.
  222. int
  223. NCursesMenu::driver (int c) {
  224.   int res = ::menu_driver (menu, c);
  225.   switch (res) {
  226.   case E_OK:
  227.   case E_REQUEST_DENIED:
  228.   case E_NOT_SELECTABLE:
  229.   case E_UNKNOWN_COMMAND:
  230.   case E_NO_MATCH:
  231.     break;
  232.   default:
  233.     OnError (res);
  234.   }
  235.   return (res);
  236. }
  237.  
  238. static const int CMD_QUIT   = MAX_COMMAND + 1;
  239. static const int CMD_ACTION = MAX_COMMAND + 2;
  240. //
  241. // -------------------------------------------------------------------------
  242. // Provide a default key virtualization. Translate the keyboard
  243. // code c into a menu request code.
  244. // The default implementation provides a hopefully straightforward
  245. // mapping for the most common keystrokes and menu requests.
  246. // -------------------------------------------------------------------------
  247. int
  248. NCursesMenu::virtualize(int c) {
  249.   switch(c) {
  250.   case CTRL('X')     : return(CMD_QUIT);              // eXit
  251.  
  252.   case KEY_DOWN      : return(REQ_DOWN_ITEM);
  253.   case CTRL('N')     : return(REQ_NEXT_ITEM);         // Next
  254.   case KEY_UP        : return(REQ_UP_ITEM);
  255.   case CTRL('P')     : return(REQ_PREV_ITEM);         // Previous
  256.  
  257.   case CTRL('U')     : return(REQ_SCR_ULINE);         // Up
  258.   case CTRL('D')     : return(REQ_SCR_DLINE);         // Down
  259.   case CTRL('F')     : return(REQ_SCR_DPAGE);         // Forward
  260.   case CTRL('B')     : return(REQ_SCR_UPAGE);         // Backward
  261.  
  262.   case CTRL('Y')     : return(REQ_CLEAR_PATTERN);
  263.   case CTRL('H')     : return(REQ_BACK_PATTERN);
  264.   case CTRL('A')     : return(REQ_NEXT_MATCH);
  265.   case CTRL('E')     : return(REQ_PREV_MATCH);
  266.   case CTRL('T')     : return(REQ_TOGGLE_ITEM);
  267.  
  268.   case CTRL('J')     :
  269.   case CTRL('M')     : return(CMD_ACTION);
  270.  
  271.   case KEY_HOME      : return(REQ_FIRST_ITEM);
  272.   case KEY_LEFT      : return(REQ_LEFT_ITEM);
  273.   case KEY_RIGHT     : return(REQ_RIGHT_ITEM);
  274.   case KEY_END       : return(REQ_LAST_ITEM);
  275.   case KEY_BACKSPACE : return(REQ_BACK_PATTERN);
  276.   case KEY_NPAGE     : return(REQ_SCR_DPAGE);
  277.   case KEY_PPAGE     : return(REQ_SCR_UPAGE);
  278.  
  279.   default:
  280.     return(c);
  281.   }
  282. }
  283.  
  284. NCursesMenuItem*
  285. NCursesMenu::operator()(void) {
  286.   int drvCmnd;
  287.   int err;
  288.   int c;
  289.   bool b_action = FALSE;
  290.  
  291.   post();
  292.   show();
  293.   refresh();
  294.   
  295.   while (!b_action && ((drvCmnd = virtualize((c=getKey()))) != CMD_QUIT)) {
  296.     
  297.     switch((err=driver(drvCmnd))) {
  298.     case E_REQUEST_DENIED:
  299.       On_Request_Denied(c);
  300.       break;
  301.     case E_NOT_SELECTABLE:
  302.       On_Not_Selectable(c);
  303.       break;
  304.     case E_UNKNOWN_COMMAND:
  305.       if (drvCmnd == CMD_ACTION) {
  306.     if (options() & O_ONEVALUE) {
  307.       NCursesMenuItem* itm = current_item();
  308.       assert(itm != 0);
  309.       if (itm->options() & O_SELECTABLE)
  310.         {
  311.           b_action = itm->action();
  312.           refresh();
  313.         }
  314.       else
  315.         On_Not_Selectable(c);
  316.     }
  317.     else {
  318.       int n = count();
  319.       for(int i=0; i<n; i++) {
  320.         NCursesMenuItem* itm = my_items[i];
  321.         if (itm->value()) {
  322.           b_action |= itm->action();
  323.           refresh();
  324.         }
  325.       }
  326.     }
  327.       } else
  328.     On_Unknown_Command(c);
  329.       break;
  330.     case E_NO_MATCH:
  331.       On_No_Match(c);
  332.       break;
  333.     case E_OK:
  334.       break;
  335.     default:
  336.       OnError(err);
  337.     }
  338.   }
  339.  
  340.   unpost();
  341.   hide();
  342.   refresh();
  343.   if (options() & O_ONEVALUE)
  344.     return my_items[::item_index (::current_item (menu))];
  345.   else
  346.     return NULL;
  347. }
  348.  
  349. void
  350. NCursesMenu::On_Menu_Init() {
  351. }
  352.  
  353. void
  354. NCursesMenu::On_Menu_Termination() {
  355. }
  356.  
  357. void
  358. NCursesMenu::On_Item_Init(NCursesMenuItem& item) {
  359. }
  360.  
  361. void
  362. NCursesMenu::On_Item_Termination(NCursesMenuItem& item) {
  363. }
  364.  
  365. void
  366. NCursesMenu::On_Request_Denied(int c) const {
  367.   ::beep();
  368. }
  369.  
  370. void
  371. NCursesMenu::On_Not_Selectable(int c) const {
  372.   ::beep();
  373. }
  374.  
  375. void
  376. NCursesMenu::On_No_Match(int c) const {
  377.   ::beep();
  378. }
  379.  
  380. void
  381. NCursesMenu::On_Unknown_Command(int c) const {
  382.   ::beep();
  383. }
  384.